﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "InplaceEditProjectProcessEventHandler.h"
#include "InplaceEditSharedContent.h"
#include "InplaceEditProjectReference.h"
#include "GmCommunicationProtocolUtils.h"
#include "EditFamilySharedContent.h"
#include "InplaceEditProcessChatServer.h"
#include "UiInplaceEditModeProjectUtil.h"
#include "ComponentEditProjectState.h"

// 平台头文件
#include "DebugMessage.h"
#include "StringUtil.h"
#include "TransferOwnership.h"
#include "GbmpNew.h"
#include "IUserTransaction.h"
#include "IMainWindow.h"
#include "IUiDocumentViewManager.h"
#include "IUiDocument.h"
#include "IModelView.h"
#include "IFamilyLoadOptions.h"
#include "FamilyLoadOptionsDefaultImpl.h"
#include "FamilyUtils.h"
#include "IUiView.h"
#include "IOnePointInstanceInput.h"
#include "IInstance.h"
#include "IFamily.h"
#include "IElementBasicInformation.h"
#include "IInstanceType.h"
#include "GbmpMoveUtils.h"
#include "IRegenerator.h"

#include "QWidget"

#include "JournalUtils.h"
#include "IJournalClient.h"
#include "InplaceEditProjectJournalMessageSender.h"
#include "ICanvas.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;

gcmp::InplaceEditProjectProcessEventHandler::~InplaceEditProjectProcessEventHandler()
{
}

gcmp::InplaceEditProjectProcessEventHandler::InplaceEditProjectProcessEventHandler()
{
}

void gcmp::InplaceEditProjectProcessEventHandler::On(OperationType operationType, OwnerPtr<NdbObject> opContent)
{
    switch (operationType)
    {
    case OperationType::Ready:
        Ready(TransferOwnership(opContent));
        break;
    case gcmp::OperationType::RequestViewData:
        RequestViewData(TransferOwnership(opContent));
        break;
    case gcmp::OperationType::FinishEditReturnToProject:
        FinishEditReturnToProject(TransferOwnership(opContent));
        break;
    case gcmp::OperationType::CancelEditReturnToProject:
        CancelEditReturnToProject(TransferOwnership(opContent));
        break;
    case gcmp::OperationType::PostJournalMessage:
        HandleJournalMessage(TransferOwnership(opContent));
        break;
    default:
        DBG_WARN(L"未识别类型：" + StringUtil::ToWString((int)operationType),L"GDMPLab",L"2024-03-30");
        break;
    }
}

void gcmp::InplaceEditProjectProcessEventHandler::Ready(OwnerPtr<NdbObject> opContent)
{
    RpcServerInfo *pContent = quick_cast<RpcServerInfo>(opContent.get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pContent, L"pContent为空",L"GDMPLab",L"2024-03-30");
    ComponentEditProjectState::Get()->SetFamilyPort(pContent->GetPort());

    CommunicationProtocolUtils::SendIpcMessage(ComponentEditProjectState::Get()->GetFamilyPort(), FunctionType::InPlaceEdit, OperationType::StartEdit, ComponentEditProjectState::Get()->GetInplaceEditSharedContent());

    OwnerPtr<InplaceEditProjectJournalMessageSender> opInplaceEditProjectJournalHandler = NEW_AS_OWNER_PTR(InplaceEditProjectJournalMessageSender, ComponentEditProjectState::Get()->GetFamilyPort());
    IJournalClient::Get()->SetJournalMessageSender(TransferOwnership(opInplaceEditProjectJournalHandler));
    IJournalClient::Get()->RequestCooperation();

    // 缓存族App端口
    InplaceEditProcessChatServer& chatServer = InplaceEditProcessChatServer::GetInstance();
    chatServer.SetFamilyPort(ComponentEditProjectState::Get()->GetFamilyPort());
}

void gcmp::InplaceEditProjectProcessEventHandler::RequestViewData(OwnerPtr<NdbObject> opContent)
{
    InplaceEditSharedModelViewInfo* pContent = quick_cast<InplaceEditSharedModelViewInfo>(opContent.get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pContent, L"pContent为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = GetCurrentDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"当前文档为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<gcmp::InplaceEditSharedViewContent> opViewContent = UiInplaceEditModeProjectUtil::GetSharedViewContent(pDoc, *pContent);
    CommunicationProtocolUtils::SendIpcSharedMemoryMessage(ComponentEditProjectState::Get()->GetFamilyPort(), OperationType::PostViewData, opViewContent.get());
}

void gcmp::InplaceEditProjectProcessEventHandler::FinishEditReturnToProject(OwnerPtr<NdbObject> opContent)
{
    EditFamilySharedContent* pContent = quick_cast<EditFamilySharedContent>(opContent.get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pContent, L"pContent为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = GetCurrentDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"当前文档为空",L"GDMPLab",L"2024-03-30");

    IModelView* pModelView = GetCurrentModelView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"当前ModelView为空",L"GDMPLab",L"2024-03-30");

    CommunicationProtocolUtils::SendIpcMessage(ComponentEditProjectState::Get()->GetFamilyPort(), FunctionType::InPlaceEdit, OperationType::EndEdit, ComponentEditProjectState::Get()->GetInplaceEditSharedContent());

    // 解冻项目App
    InplaceEditProcessChatServer& chatServer = InplaceEditProcessChatServer::GetInstance();
    chatServer.Stop();

    // 最大化主窗口
    QWidget* pWidget = dynamic_cast<QWidget*>(IMainWindow::GetMainWindow());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pWidget, L"pWidget为空",L"GDMPLab",L"2024-03-30");
    pWidget->setWindowState(Qt::WindowMaximized);

    OwnerPtr<IUserTransaction> opTransaction = IUserTransaction::Create(pDoc, GBMP_TR(L"完成编辑并返回项目环境"), true);
    DBG_WARN_AND_RETURN_VOID_UNLESS(opTransaction, L"opTransaction为空",L"GDMPLab",L"2024-03-30");

    // 加载族文档
    std::wstring errorMsg;
    FamilyLoadOptionsDefaultImpl familyLoadOptionsImpl(gcmp::FamilyFoundStrategy::FF_Overwrite);
    const std::wstring familyFilePath = pContent->GetEditFamilyFilePath();
    IFamily* pIFamily = FamilyUtils::LoadFamily(pDoc, familyFilePath, errorMsg, &familyLoadOptionsImpl);

    DBG_WARN_AND_RETURN_VOID_UNLESS(pIFamily, L"加载族文档失败",L"GDMPLab",L"2024-03-30");
    bool isCreating = ComponentEditProjectState::Get()->GetIsCreating();
    if (isCreating)
    {
        ElementId workPlaneId = ComponentEditProjectState::Get()->GetWorkLevelId();
        DBG_WARN_AND_RETURN_VOID_UNLESS(workPlaneId.IsValid(), L"workPlaneId无效",L"GDMPLab",L"2024-03-30");
       
        const std::wstring familyName = pContent->GetFamilyName();
        const IFamily* pFamily = IFamily::GetFamilyByName(pDoc, familyName);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamily, L"pFamily为空",L"GDMPLab",L"2024-03-30");
        ElementId familyId = pFamily->GetElementId();
        DBG_WARN_AND_RETURN_VOID_UNLESS(familyId.IsValid(), L"familyId无效",L"GDMPLab",L"2024-03-30");
       
        // GetFirstInstanceType
        std::wstring instanceType;
        const std::vector<IInstanceType*> instanceTypes = pFamily->GetInstanceTypes();
        DBG_WARN_AND_RETURN_VOID_UNLESS(instanceTypes.size() > 0, L"instanceTypes为空",L"GDMPLab",L"2024-03-30");
        instanceType = instanceTypes[0]->GetBasicInformation()->GetName();
        DBG_WARN_AND_RETURN_VOID_UNLESS(!instanceType.empty(), L"instanceType为空",L"GDMPLab",L"2024-03-30");

        // 创建点式族
        OwnerPtr<IOnePointInstanceInput> opInput = IOnePointInstanceInput::Create(pDoc, workPlaneId, familyId, instanceType);
        IInstance* pInstance = IInstance::CreateByOnePoint(opInput.get());
        DBG_WARN_AND_RETURN_VOID_UNLESS(pInstance, L"创建实例失败",L"GDMPLab",L"2024-03-30");

        // 移动至插入点
        InplaceEditSharedContent* pInplaceEditSharedContent = ComponentEditProjectState::Get()->GetInplaceEditSharedContent();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pInplaceEditSharedContent, L"获取在位编辑共享信息失败",L"GDMPLab",L"2024-03-30");
        Vector3d insertPoint = pInplaceEditSharedContent->GetInsertionPoint();
        Vector3d origin = Vector3d();
        GbmpMoveUtils::MoveElement(pInstance, origin, insertPoint, pModelView);

        gcmp::IRegenerator* pRegenerator = pDoc->GetRegenerator();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRegenerator, L"pRegenerator为空",L"GDMPLab",L"2024-03-30");
        pRegenerator->RegenerateElement(pInstance->GetElementId());
    }

    opTransaction->Commit();

    IUiView* pUiView = IUiDocumentViewManager::Get()->GetCurrentUiView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiView, L"pUiView为空",L"GDMPLab",L"2024-03-30");
    ICanvas *pCanvas = pUiView->GetCanvas();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCanvas != nullptr, L"ICanvas指针无效",L"GDMPLab",L"2024-03-30");
    pCanvas->Refresh();
}

void gcmp::InplaceEditProjectProcessEventHandler::CancelEditReturnToProject(OwnerPtr<NdbObject> opContent)
{
    CommunicationProtocolUtils::SendIpcMessage(ComponentEditProjectState::Get()->GetFamilyPort(), FunctionType::InPlaceEdit, OperationType::EndEdit, ComponentEditProjectState::Get()->GetInplaceEditSharedContent());

    // 解冻项目App
    InplaceEditProcessChatServer& chatServer = InplaceEditProcessChatServer::GetInstance();
    chatServer.Stop();

    // 最大化主窗口
    QWidget* pWidget = dynamic_cast<QWidget*>(IMainWindow::GetMainWindow());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pWidget, L"pWidget为空",L"GDMPLab",L"2024-03-30");
    pWidget->setWindowState(Qt::WindowMaximized);
}

void InplaceEditProjectProcessEventHandler::HandleJournalMessage(OwnerPtr<NdbObject> opContent)
{
    InplaceEditSharedJournalContent* pContent = quick_cast<InplaceEditSharedJournalContent>(opContent.get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pContent, L"pContent为空",L"GDMPLab",L"2024-03-30");

    const std::map<std::wstring, std::wstring> &journalMessage = pContent->GetJournalMessage();
    IJournalClient *pJournalClient = IJournalClient::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pJournalClient, L"pJournalClient为空",L"GDMPLab",L"2024-03-30");

    pJournalClient->Handle(journalMessage);
}

IUiDocument* gcmp::InplaceEditProjectProcessEventHandler::GetCurrentUiDocument()
{
    IUiDocumentViewManager* pUiDocManager = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDocManager, L"pUiDocManager为空",L"GDMPLab",L"2024-03-30");

    IUiDocument* pUiDoc = pUiDocManager->GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
    return pUiDoc;
}

IDocument* gcmp::InplaceEditProjectProcessEventHandler::GetCurrentDocument()
{
    IUiDocument* pUiDoc = GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
    return pUiDoc->GetDbDocument();
}

IModelView* gcmp::InplaceEditProjectProcessEventHandler::GetCurrentModelView()
{
    IUiDocumentViewManager* pUiDocManager = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDocManager, L"pUiDocManager为空",L"GDMPLab",L"2024-03-30");

    IUiView* pUiView = pUiDocManager->GetCurrentUiView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiView, L"pUiView为空",L"GDMPLab",L"2024-03-30");

    IModelView* pModelView = pUiView->GetModelView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    return pModelView;
}
